# -*- coding: utf-8 -*-
"""
@Time    : 2024/8/27 15:39 
@Author  : ZhangShenao 
@File    : 2.工具调用模式的Agent.py 
@Desc    : 工具调用模式的Tools Agent

基于ChatModel + ChatPromptTemplate + Tool Call
可以实现更强大的工具调用模式的Agent
相较于传统的ReACT模式,工具调用模式的Agent生成的答案更稳定、性能也更高

在Tools Agent模式下,LLM通过判断生成的内容是普通文本还是工具调用,来决定Agent下一步的执行步骤
如果生成的是普通文本,则说明获取到了最终结果,会返回AgentFinish
如果生成的是tool_calls,则说明下一步需要调用工具,会返回AgentAction,并将工具调用信息封装在其中

"""
import os

import dotenv
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI

from dalle_image_tool import create_dalle_image_tool
from google_serper_tool import create_google_serper_tool

# 加载环境变量
dotenv.load_dotenv()

# 创建工具列表
tools = [create_google_serper_tool(), create_dalle_image_tool()]

# 构造Tools Agent模式的Prompt
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个强大的AI智能助手，善于帮助用户解决问题。如果需要，可以调用外部工具。"),
    ("placeholder", "{chat_history}"),
    ("human", "{input}"),
    ("placeholder", "{agent_scratchpad}"),
])

# 创建LLM
llm = ChatOpenAI(model="gpt-4o-mini", openai_api_base=os.getenv("OPENAI_API_BASE"))

# 创建Tool Calling Agent
tool_call_agent = create_tool_calling_agent(
    llm=llm,  # 指定LLM
    prompt=prompt,  # 指定Prompt
    tools=tools,  # 绑定工具列表
)

# 创建Agent执行器
executor = AgentExecutor(
    agent=tool_call_agent,  # 指定Agent
    tools=tools,  # 指定工具列表
    verbose=True,  # 打印中间过程
)

# 调用执行器,开始执行Agent
input = """
请帮我搜索一个最近网络上比较火的虚拟角色，为我生成这个角色的姓名和简介，并画一张关于这个角色的图片。
请按照以下格式生成：

角色名：

角色简介：

角色图片：

"""

result = executor.invoke({"input": input})

print(result)
